#pragma once

#include <string>
#include <vector>
#include "sqlite3pp.h"
#include <boost/lexical_cast.hpp>

class MSqldb;

class MKVdb
{
public:
	MKVdb(sqlite3pp::database *db);
	~MKVdb();

	void set(const std::string &key,const std::string &value);
	std::string getWithDefault(const std::string &key, const std::string &dft = "");
	bool get(const std::string &key, std::string &value);
	void del(const std::string &key);
	bool has(const std::string &key);

	template<typename T>
	void setT(const std::string &key, const T &value)
	{
		std::stringstream ss;
		ss << value;
		set(key, ss.str());
	}

	template<typename T>
	T getT(const std::string &key, const T &value)
	{
		std::string s;
		if (get(key, s))
		{
			return boost::lexical_cast<T>(s);
		}
		else
		{
			return value;
		} 
	}

private:
	sqlite3pp::database *m_db;
};


struct MDocData 
{
	std::string id;
	std::string src_data;
	std::string cur_data;
	int version;
	int change_flag;
	int create_flag;
};

struct MDirData
{
	std::string id;
	std::string src_data;
	std::string cur_data;
	int version;
	int change_flag;
};

class MDocdb
{
public:
	MDocdb(sqlite3pp::database *db);
	~MDocdb();

	void createDocLocal(const std::string &docId, const std::string &curData);
	void delDocsLocal(const std::vector<std::string> &docIds);
	void updateDocLocal(const std::string &docId, const std::string &curData);

	void resetChangeFlag(const std::string &docIds);
	void getChangeDocs(std::vector<MDocData> &docs);

	void updateDocAfterUpload(const std::string &docId, const std::string &content, int version);
	void refreshChangeFlag();

	bool getDoc(const std::string &docId, MDocData &data);
	void setDoc(const MDocData &data);

private:
	sqlite3pp::database *m_db;
};

class MDirDB
{
public:
	MDirDB(sqlite3pp::database *db);
	~MDirDB();

	void changeDirLocal(const std::string &dirId, const std::string &content);
 	void resetChangeFlag(const std::string &dirId);

	bool isChange(const std::string &dirId);

	void updateDocAfterUpload(const std::string &docId, const std::string &content, int version);
	void refreshChangeFlag(const std::string &docId);

	bool getDir(const std::string &dirId, MDirData &data);
	void setDir(const MDirData &data);

private:
	sqlite3pp::database *m_db;
};

class MSqldb
{
public:
	MSqldb();
	~MSqldb();

	bool instance(const std::string &workPath);

	MKVdb *getKVDB() { return m_kvdb; }
	MDocdb *getDocDB() { return m_docdb; }
	MDirDB *getDirDB() { return m_dirdb; }
private:
	MKVdb *m_kvdb;
	MDocdb *m_docdb;
	MDirDB *m_dirdb;

	sqlite3pp::database m_db;
};

